/*-------------------------------------------------------------------------
 *
 * jsonb_util.c
 *	  在 Jsonb 和 JsonbValues 之间转换，并进行迭代。
 *
 * Copyright (c) 2014-2022, PostgreSQL Global Development Group
 *
 *
 * IDENTIFICATION
 *	  src/backend/utils/adt/jsonb_util.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "common/hashfn.h"
#include "common/jsonapi.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
#include "utils/json.h"
#include "utils/jsonb.h"
#include "utils/memutils.h"
#include "utils/varlena.h"

/*
 * 数组中元素的最大数量（或对象中的键/值对）。
 * 这受两件事的限制：JEntry 数组的大小必须适合
 * MaxAllocSize，元素（或对）的数量必须适合
 * JsonbContainer.header 字段中为此保留的位数。
 *
 * （数组或对象的元素总大小也受到 JENTRY_OFFLENMASK 的限制，
 * 但我们在这里不关心。）
 */
#define JSONB_MAX_ELEMS (Min(MaxAllocSize / sizeof(JsonbValue), JB_CMASK))
#define JSONB_MAX_PAIRS (Min(MaxAllocSize / sizeof(JsonbPair), JB_CMASK))

static void fc_fillJsonbValue(JsonbContainer *fc_container, int fc_index,
						   char *fc_base_addr, uint32 fc_offset,
						   JsonbValue *fc_result);
static bool fc_equalsJsonbScalarValue(JsonbValue *fc_a, JsonbValue *fc_b);
static int	fc_compareJsonbScalarValue(JsonbValue *fc_a, JsonbValue *fc_b);
static Jsonb *fc_convertToJsonb(JsonbValue *fc_val);
static void fc_convertJsonbValue(StringInfo fc_buffer, JEntry *fc_header, JsonbValue *fc_val, int fc_level);
static void fc_convertJsonbArray(StringInfo fc_buffer, JEntry *fc_header, JsonbValue *fc_val, int fc_level);
static void fc_convertJsonbObject(StringInfo fc_buffer, JEntry *fc_header, JsonbValue *fc_val, int fc_level);
static void fc_convertJsonbScalar(StringInfo fc_buffer, JEntry *fc_header, JsonbValue *fc_scalarVal);

static int	fc_reserveFromBuffer(StringInfo fc_buffer, int fc_len);
static void fc_appendToBuffer(StringInfo fc_buffer, const char *fc_data, int fc_len);
static void fc_copyToBuffer(StringInfo fc_buffer, int fc_offset, const char *fc_data, int fc_len);
static short fc_padBufferToInt(StringInfo fc_buffer);

static JsonbIterator *fc_iteratorFromContainer(JsonbContainer *fc_container, JsonbIterator *fc_parent);
static JsonbIterator *fc_freeAndGetParent(JsonbIterator *fc_it);
static JsonbParseState *fc_pushState(JsonbParseState **fc_pstate);
static void fc_appendKey(JsonbParseState *fc_pstate, JsonbValue *fc_scalarVal);
static void fc_appendValue(JsonbParseState *fc_pstate, JsonbValue *fc_scalarVal);
static void fc_appendElement(JsonbParseState *fc_pstate, JsonbValue *fc_scalarVal);
static int	fc_lengthCompareJsonbStringValue(const void *fc_a, const void *fc_b);
static int	fc_lengthCompareJsonbString(const char *fc_val1, int fc_len1,
									 const char *fc_val2, int fc_len2);
static int	fc_lengthCompareJsonbPair(const void *fc_a, const void *fc_b, void *fc_arg);
static void fc_uniqueifyJsonbObject(JsonbValue *fc_object);
static JsonbValue *fc_pushJsonbValueScalar(JsonbParseState **fc_pstate,
										JsonbIteratorToken fc_seq,
										JsonbValue *fc_scalarVal);

void JsonbToJsonbValue(Jsonb *fc_jsonb, JsonbValue *fc_val)
{
	fc_val->type = jbvBinary;
	fc_val->val.binary.data = &fc_jsonb->root;
	fc_val->val.binary.len = VARSIZE(fc_jsonb) - VARHDRSZ;
}


Jsonb *
JsonbValueToJsonb(JsonbValue *fc_val)
{
	Jsonb	   *fc_out;

	if (IsAJsonbScalar(fc_val))
	{
		/* 标量值 */
		JsonbParseState *fc_pstate = NULL;
		JsonbValue *fc_res;
		JsonbValue	fc_scalarArray;

		fc_scalarArray.type = jbvArray;
		fc_scalarArray.val.array.rawScalar = true;
		fc_scalarArray.val.array.nElems = 1;

		pushJsonbValue(&fc_pstate, WJB_BEGIN_ARRAY, &fc_scalarArray);
		pushJsonbValue(&fc_pstate, WJB_ELEM, fc_val);
		fc_res = pushJsonbValue(&fc_pstate, WJB_END_ARRAY, NULL);

		fc_out = fc_convertToJsonb(fc_res);
	}
	else if (fc_val->type == jbvObject || fc_val->type == jbvArray)
	{
		fc_out = fc_convertToJsonb(fc_val);
	}
	else
	{
		Assert(fc_val->type == jbvBinary);
		fc_out = palloc(VARHDRSZ + fc_val->val.binary.len);
		SET_VARSIZE(fc_out, VARHDRSZ + fc_val->val.binary.len);
		memcpy(VARDATA(fc_out), fc_val->val.binary.data, fc_val->val.binary.len);
	}

	return fc_out;
}

/*
 * 获取 Jsonb 节点在其容器的可变长度数据部分中的可变长度部分的偏移量。该节点通过容器的 JEntry 数组中的索引进行识别。
 */
uint32 getJsonbOffset(const JsonbContainer *fc_jc, int fc_index)
{
	uint32		fc_offset = 0;
	int			fc_i;

	/*
	 * 该条目的起始偏移量等于前一个条目的结束偏移量。向后查找以获取最近存储为结束偏移量的条目，返回该偏移量加上任何之间的长度。
	 */
	for (fc_i = fc_index - 1; fc_i >= 0; fc_i--)
	{
		fc_offset += JBE_OFFLENFLD(fc_jc->children[fc_i]);
		if (JBE_HAS_OFF(fc_jc->children[fc_i]))
			break;
	}

	return fc_offset;
}

/*
 * 获取 Jsonb 节点的可变长度部分的长度。该节点通过容器的 JEntry 数组中的索引进行识别。
 */
uint32 getJsonbLength(const JsonbContainer *fc_jc, int fc_index)
{
	uint32		fc_off;
	uint32		fc_len;

	/*
	 * 如果长度直接存储在 JEntry 中，则直接返回它。
	 * 否则，获取条目的起始偏移量，并从存储的结束+1 偏移量中减去该值。
	 */
	if (JBE_HAS_OFF(fc_jc->children[fc_index]))
	{
		fc_off = getJsonbOffset(fc_jc, fc_index);
		fc_len = JBE_OFFLENFLD(fc_jc->children[fc_index]) - fc_off;
	}
	else
		fc_len = JBE_OFFLENFLD(fc_jc->children[fc_index]);

	return fc_len;
}

/*
 * BT 比较器工作函数。返回一个小于、等于或大于零的整数，指示 a 是否小于、等于或大于 b。与 B-Tree 操作符类的要求一致。
 *
 * 字符串按词法进行比较，与我们在其他地方通过使用更简单的比较逻辑搜索字符串的方式形成对比。由于这是从 B-Tree 支持函数 1 中调用的，我们小心不要在这里泄漏内存。
 */
int compareJsonbContainers(JsonbContainer *fc_a, JsonbContainer *fc_b)
{
	JsonbIterator *fc_ita,
			   *fc_itb;
	int			fc_res = 0;

	fc_ita = JsonbIteratorInit(fc_a);
	fc_itb = JsonbIteratorInit(fc_b);

	do
	{
		JsonbValue	fc_va,
					fc_vb;
		JsonbIteratorToken fc_ra,
					fc_rb;

		fc_ra = JsonbIteratorNext(&fc_ita, &fc_va, false);
		fc_rb = JsonbIteratorNext(&fc_itb, &fc_vb, false);

		if (fc_ra == fc_rb)
		{
			if (fc_ra == WJB_DONE)
			{
				/* 决定性相等 */
				break;
			}

			if (fc_ra == WJB_END_ARRAY || fc_ra == WJB_END_OBJECT)
			{
				/*
				 * 在处理的这一阶段没有数组或对象可以比较。jbvArray/jbvObject 值最初在 WJB_BEGIN_ARRAY 和 WJB_BEGIN_OBJECT 标记处进行比较。
				 */
				continue;
			}

			if (fc_va.type == fc_vb.type)
			{
				switch (fc_va.type)
				{
					case jbvString:
					case jbvNull:
					case jbvNumeric:
					case jbvBool:
						fc_res = fc_compareJsonbScalarValue(&fc_va, &fc_vb);
						break;
					case jbvArray:

						/*
						 * 这可能是一个“原始标量”伪数组。不过这是一种特殊情况，因为我们仍然希望适用一般的基于类型的比较，就我们而言，伪数组只是一个标量。
						 */
						if (fc_va.val.array.rawScalar != fc_vb.val.array.rawScalar)
							fc_res = (fc_va.val.array.rawScalar) ? -1 : 1;
						if (fc_va.val.array.nElems != fc_vb.val.array.nElems)
							fc_res = (fc_va.val.array.nElems > fc_vb.val.array.nElems) ? 1 : -1;
						break;
					case jbvObject:
						if (fc_va.val.object.nPairs != fc_vb.val.object.nPairs)
							fc_res = (fc_va.val.object.nPairs > fc_vb.val.object.nPairs) ? 1 : -1;
						break;
					case jbvBinary:
						elog(ERROR, "unexpected jbvBinary value");
						break;
					case jbvDatetime:
						elog(ERROR, "unexpected jbvDatetime value");
						break;
				}
			}
			else
			{
				/* 类型定义顺序 */
				fc_res = (fc_va.type > fc_vb.type) ? 1 : -1;
			}
		}
		else
		{
			/*
			 * 可以安全地假设类型不同，并且传入的 va 和 vb 值已被设置。
			 *
			 * 如果两个值是相同的容器类型，那么在处理 WJB_BEGIN_OBJECT 时会有机会观察到元素/对的数量变化。它们要么是两个异构类型的容器，要么是一个容器和某种标量类型。
			 *
			 * 我们在这里不需要考虑 WJB_END_ARRAY 和 WJB_END_OBJECT 的情况，因为我们会首先看到相应的 WJB_BEGIN_ARRAY 和 WJB_BEGIN_OBJECT 标记，并得出它们不匹配的结论。
			 */
			Assert(fc_ra != WJB_END_ARRAY && fc_ra != WJB_END_OBJECT);
			Assert(fc_rb != WJB_END_ARRAY && fc_rb != WJB_END_OBJECT);

			Assert(fc_va.type != fc_vb.type);
			Assert(fc_va.type != jbvBinary);
			Assert(fc_vb.type != jbvBinary);
			/* 类型定义顺序 */
			fc_res = (fc_va.type > fc_vb.type) ? 1 : -1;
		}
	}
	while (fc_res == 0);

	while (fc_ita != NULL)
	{
		JsonbIterator *fc_i = fc_ita->parent;

		pfree(fc_ita);
		fc_ita = fc_i;
	}
	while (fc_itb != NULL)
	{
		JsonbIterator *fc_i = fc_itb->parent;

		pfree(fc_itb);
		fc_itb = fc_i;
	}

	return fc_res;
}

/*
 * 在对象中查找值（即对象中某个键/值对的“值”部分），或者在查找数组时查找匹配的元素。仅基于对象键的相等性，或者仅基于元素值，与调用者提供的值“键”。“flags”参数允许调用者指定感兴趣的容器类型。
 *
 * 这个导出的实用函数用于方便处理各种与“包含”相关的情况。如果被要求查看对象，调用者最好传递一个 Jsonb 字符串，因为它们的键只能是字符串。否则，对于数组，任何类型的 JsonbValue 都可以。
 *
 * 为了继续搜索，调用者必须明确对一个特定容器类型表示兴趣，并使用适当的标志，同时所指向的 Jsonb 容器必须处于同样的容器类型的顶层。（实际上，我们会做任何合乎逻辑的事情，以便节省调用者查找的麻烦 - 大多数情况下只能使一个容器有意义，因为容器要么指向数组（可能是“原始标量”伪数组），要么指向对象。）
 *
 * 请注意，如果在对象上调用此函数，我们可以返回 jbvBinary JsonbValue，但在数组上从不这样做。如果调用者请求查看一个不属于容器所指向类型的容器类型，立即跳过并返回 NULL。如果我们无法找到该值，则返回 NULL。否则，返回 palloc() 的副本。
 */
JsonbValue * findJsonbValueFromContainer(JsonbContainer *fc_container, uint32 fc_flags,
							JsonbValue *fc_key)
{
	JEntry	   *fc_children = fc_container->children;
	int			fc_count = JsonContainerSize(fc_container);

	Assert((fc_flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);

	/* 如果对象/数组为空，则无需 palloc 循环即可快速返回 */
	if (fc_count <= 0)
		return NULL;

	if ((fc_flags & JB_FARRAY) && JsonContainerIsArray(fc_container))
	{
		JsonbValue *fc_result = palloc(sizeof(JsonbValue));
		char	   *fc_base_addr = (char *) (fc_children + fc_count);
		uint32		fc_offset = 0;
		int			fc_i;

		for (fc_i = 0; fc_i < fc_count; fc_i++)
		{
			fc_fillJsonbValue(fc_container, fc_i, fc_base_addr, fc_offset, fc_result);

			if (fc_key->type == fc_result->type)
			{
				if (fc_equalsJsonbScalarValue(fc_key, fc_result))
					return fc_result;
			}

			JBE_ADVANCE_OFFSET(fc_offset, fc_children[fc_i]);
		}

		pfree(fc_result);
	}
	else if ((fc_flags & JB_FOBJECT) && JsonContainerIsObject(fc_container))
	{
		/* 调用者传递的对象键必须是字符串 */
		Assert(fc_key->type == jbvString);

		return getKeyJsonValueFromContainer(fc_container, fc_key->val.string.val,
											fc_key->val.string.len, NULL);
	}

	/* 未找到 */
	return NULL;
}

/*
 * 通过键在 Jsonb 对象中查找值，并将其提取到 'res' 中，同时返回该值。
 *
 * 'res' 可以传递为 NULL，在这种情况下，它将在这里新分配内存。
 */
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *fc_container,
							 const char *fc_keyVal, int fc_keyLen, JsonbValue *fc_res)
{
	JEntry	   *fc_children = fc_container->children;
	int			fc_count = JsonContainerSize(fc_container);
	char	   *fc_baseAddr;
	uint32		fc_stopLow,
				fc_stopHigh;

	Assert(JsonContainerIsObject(fc_container));

	/* 如果对象为空，则无需 palloc 循环即可快速返回 */
	if (fc_count <= 0)
		return NULL;

	/*
	 * 对容器进行二分搜索。因为我们知道这是一个对象，考虑 *Pairs* 的 Jentrys。
	 */
	fc_baseAddr = (char *) (fc_children + fc_count * 2);
	fc_stopLow = 0;
	fc_stopHigh = fc_count;
	while (fc_stopLow < fc_stopHigh)
	{
		uint32		fc_stopMiddle;
		int			fc_difference;
		const char *fc_candidateVal;
		int			fc_candidateLen;

		fc_stopMiddle = fc_stopLow + (fc_stopHigh - fc_stopLow) / 2;

		fc_candidateVal = fc_baseAddr + getJsonbOffset(fc_container, fc_stopMiddle);
		fc_candidateLen = getJsonbLength(fc_container, fc_stopMiddle);

		fc_difference = fc_lengthCompareJsonbString(fc_candidateVal, fc_candidateLen,
											  fc_keyVal, fc_keyLen);

		if (fc_difference == 0)
		{
			/* 找到了我们的键，返回相应的值 */
			int			fc_index = fc_stopMiddle + fc_count;

			if (!fc_res)
				fc_res = palloc(sizeof(JsonbValue));

			fc_fillJsonbValue(fc_container, fc_index, fc_baseAddr,
						   getJsonbOffset(fc_container, fc_index),
						   fc_res);

			return fc_res;
		}
		else
		{
			if (fc_difference < 0)
				fc_stopLow = fc_stopMiddle + 1;
			else
				fc_stopHigh = fc_stopMiddle;
		}
	}

	/* 未找到 */
	return NULL;
}

/*
 * 获取 Jsonb 数组的第 i 个值。
 *
 * 返回 palloc() 的值副本，如果不存在则返回 NULL。
 */
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *fc_container, uint32 fc_i)
{
	JsonbValue *fc_result;
	char	   *fc_base_addr;
	uint32		fc_nelements;

	if (!JsonContainerIsArray(fc_container))
		elog(ERROR, "not a jsonb array");

	fc_nelements = JsonContainerSize(fc_container);
	fc_base_addr = (char *) &fc_container->children[fc_nelements];

	if (fc_i >= fc_nelements)
		return NULL;

	fc_result = palloc(sizeof(JsonbValue));

	fc_fillJsonbValue(fc_container, fc_i, fc_base_addr,
				   getJsonbOffset(fc_container, fc_i),
				   fc_result);

	return fc_result;
}


/*
 * 一个辅助函数，用于填充JsonbValue，以表示数组的元素，或对象的键或值。
 *
 * 节点的JEntry位于container->children[index]，其变长数据位于base_addr + offset。我们让调用者确定偏移量，因为在许多情况下，调用者可以在多个子项之间摊销这项工作。当无法做到时，它可以直接调用getJsonbOffset()。
 *
 * 嵌套的数组或对象将作为jbvBinary返回，即它不会被展开。
 */
static void fc_fillJsonbValue(JsonbContainer *fc_container, int fc_index,
			   char *fc_base_addr, uint32 fc_offset,
			   JsonbValue *fc_result)
{
	JEntry		fc_entry = fc_container->children[fc_index];

	if (JBE_ISNULL(fc_entry))
	{
		fc_result->type = jbvNull;
	}
	else if (JBE_ISSTRING(fc_entry))
	{
		fc_result->type = jbvString;
		fc_result->val.string.val = fc_base_addr + fc_offset;
		fc_result->val.string.len = getJsonbLength(fc_container, fc_index);
		Assert(fc_result->val.string.len >= 0);
	}
	else if (JBE_ISNUMERIC(fc_entry))
	{
		fc_result->type = jbvNumeric;
		fc_result->val.numeric = (Numeric) (fc_base_addr + INTALIGN(fc_offset));
	}
	else if (JBE_ISBOOL_TRUE(fc_entry))
	{
		fc_result->type = jbvBool;
		fc_result->val.boolean = true;
	}
	else if (JBE_ISBOOL_FALSE(fc_entry))
	{
		fc_result->type = jbvBool;
		fc_result->val.boolean = false;
	}
	else
	{
		Assert(JBE_ISCONTAINER(fc_entry));
		fc_result->type = jbvBinary;
		/* 从数据指针和长度中移除对齐填充 */
		fc_result->val.binary.data = (JsonbContainer *) (fc_base_addr + INTALIGN(fc_offset));
		fc_result->val.binary.len = getJsonbLength(fc_container, fc_index) -
			(INTALIGN(fc_offset) - fc_offset);
	}
}

/*
 * 将JsonbValue推送到JsonbParseState中。
 *
 * 在解析JSON令牌以形成Jsonb时使用，或在将内存中的JsonbValue转换为Jsonb时使用。
 *
 * *JsonbParseState的初始状态为NULL，因为它将在这里原始分配（调用者将通过引用获取JsonbParseState）。
 *
 * 只有与非容器类型相关的顺序令牌应传递JsonbValue。唯一的例外是--WJB_BEGIN_ARRAY调用者可以传递一个“原始标量”伪数组以追加它--实际的标量应在下一步传递，它将作为数组的唯一成员添加。
 *
 * 类型为jbvBinary的值，这是汇总的数组和对象，在添加到结果之前会被解包。
 */
JsonbValue * pushJsonbValue(JsonbParseState **fc_pstate, JsonbIteratorToken fc_seq,
			   JsonbValue *fc_jbval)
{
	JsonbIterator *fc_it;
	JsonbValue *fc_res = NULL;
	JsonbValue	fc_v;
	JsonbIteratorToken fc_tok;
	int			fc_i;

	if (fc_jbval && (fc_seq == WJB_ELEM || fc_seq == WJB_VALUE) && fc_jbval->type == jbvObject)
	{
		pushJsonbValue(fc_pstate, WJB_BEGIN_OBJECT, NULL);
		for (fc_i = 0; fc_i < fc_jbval->val.object.nPairs; fc_i++)
		{
			pushJsonbValue(fc_pstate, WJB_KEY, &fc_jbval->val.object.pairs[fc_i].key);
			pushJsonbValue(fc_pstate, WJB_VALUE, &fc_jbval->val.object.pairs[fc_i].value);
		}

		return pushJsonbValue(fc_pstate, WJB_END_OBJECT, NULL);
	}

	if (fc_jbval && (fc_seq == WJB_ELEM || fc_seq == WJB_VALUE) && fc_jbval->type == jbvArray)
	{
		pushJsonbValue(fc_pstate, WJB_BEGIN_ARRAY, NULL);
		for (fc_i = 0; fc_i < fc_jbval->val.array.nElems; fc_i++)
		{
			pushJsonbValue(fc_pstate, WJB_ELEM, &fc_jbval->val.array.elems[fc_i]);
		}

		return pushJsonbValue(fc_pstate, WJB_END_ARRAY, NULL);
	}

	if (!fc_jbval || (fc_seq != WJB_ELEM && fc_seq != WJB_VALUE) ||
		fc_jbval->type != jbvBinary)
	{
		/* 继续到下一个 */
		return fc_pushJsonbValueScalar(fc_pstate, fc_seq, fc_jbval);
	}

	/* 解包二进制数据并将每个部分添加到pstate中 */
	fc_it = JsonbIteratorInit(fc_jbval->val.binary.data);

	if ((fc_jbval->val.binary.data->header & JB_FSCALAR) && *fc_pstate)
	{
		fc_tok = JsonbIteratorNext(&fc_it, &fc_v, true);
		Assert(fc_tok == WJB_BEGIN_ARRAY);
		Assert(fc_v.type == jbvArray && fc_v.val.array.rawScalar);

		fc_tok = JsonbIteratorNext(&fc_it, &fc_v, true);
		Assert(fc_tok == WJB_ELEM);

		fc_res = fc_pushJsonbValueScalar(fc_pstate, fc_seq, &fc_v);

		fc_tok = JsonbIteratorNext(&fc_it, &fc_v, true);
		Assert(fc_tok == WJB_END_ARRAY);
		Assert(fc_it == NULL);

		return fc_res;
	}

	while ((fc_tok = JsonbIteratorNext(&fc_it, &fc_v, false)) != WJB_DONE)
		fc_res = fc_pushJsonbValueScalar(fc_pstate, fc_tok,
								   fc_tok < WJB_BEGIN_ARRAY ||
								   (fc_tok == WJB_BEGIN_ARRAY &&
									fc_v.val.array.rawScalar) ? &fc_v : NULL);

	return fc_res;
}

/*
 * 执行实际的推送，只接受标量或伪标量数组值。
 */
static JsonbValue * fc_pushJsonbValueScalar(JsonbParseState **fc_pstate, JsonbIteratorToken fc_seq,
					 JsonbValue *fc_scalarVal)
{
	JsonbValue *fc_result = NULL;

	switch (fc_seq)
	{
		case WJB_BEGIN_ARRAY:
			Assert(!fc_scalarVal || fc_scalarVal->val.array.rawScalar);
			*fc_pstate = fc_pushState(fc_pstate);
			fc_result = &(*fc_pstate)->contVal;
			(*fc_pstate)->contVal.type = jbvArray;
			(*fc_pstate)->contVal.val.array.nElems = 0;
			(*fc_pstate)->contVal.val.array.rawScalar = (fc_scalarVal &&
													  fc_scalarVal->val.array.rawScalar);
			if (fc_scalarVal && fc_scalarVal->val.array.nElems > 0)
			{
				/* 假设这个数组仍然是一个标量 */
				Assert(fc_scalarVal->type == jbvArray);
				(*fc_pstate)->size = fc_scalarVal->val.array.nElems;
			}
			else
			{
				(*fc_pstate)->size = 4;
			}
			(*fc_pstate)->contVal.val.array.elems = palloc(sizeof(JsonbValue) *
														(*fc_pstate)->size);
			break;
		case WJB_BEGIN_OBJECT:
			Assert(!fc_scalarVal);
			*fc_pstate = fc_pushState(fc_pstate);
			fc_result = &(*fc_pstate)->contVal;
			(*fc_pstate)->contVal.type = jbvObject;
			(*fc_pstate)->contVal.val.object.nPairs = 0;
			(*fc_pstate)->size = 4;
			(*fc_pstate)->contVal.val.object.pairs = palloc(sizeof(JsonbPair) *
														 (*fc_pstate)->size);
			break;
		case WJB_KEY:
			Assert(fc_scalarVal->type == jbvString);
			fc_appendKey(*fc_pstate, fc_scalarVal);
			break;
		case WJB_VALUE:
			Assert(IsAJsonbScalar(fc_scalarVal));
			fc_appendValue(*fc_pstate, fc_scalarVal);
			break;
		case WJB_ELEM:
			Assert(IsAJsonbScalar(fc_scalarVal));
			fc_appendElement(*fc_pstate, fc_scalarVal);
			break;
		case WJB_END_OBJECT:
			fc_uniqueifyJsonbObject(&(*fc_pstate)->contVal);
			/* fall through! */
		case WJB_END_ARRAY:
			/* 此处步骤在WJB_END_OBJECT情况下是通用的 */
			Assert(!fc_scalarVal);
			fc_result = &(*fc_pstate)->contVal;

			/*
			 * 弹出栈并将当前数组/对象作为父数组/对象中的值推送
			 */
			*fc_pstate = (*fc_pstate)->next;
			if (*fc_pstate)
			{
				switch ((*fc_pstate)->contVal.type)
				{
					case jbvArray:
						fc_appendElement(*fc_pstate, fc_result);
						break;
					case jbvObject:
						fc_appendValue(*fc_pstate, fc_result);
						break;
					default:
						elog(ERROR, "invalid jsonb container type");
				}
			}
			break;
		default:
			elog(ERROR, "unrecognized jsonb sequential processing token");
	}

	return fc_result;
}

/*
 * pushJsonbValue()工作程序：类似于迭代的Jsonb形成
 */
static JsonbParseState *
fc_pushState(JsonbParseState **fc_pstate)
{
	JsonbParseState *fc_ns = palloc(sizeof(JsonbParseState));

	fc_ns->next = *fc_pstate;
	return fc_ns;
}

/*
 * pushJsonbValue() worker:  在生成 Jsonb 时将键对附加到状态
 */
static void fc_appendKey(JsonbParseState *fc_pstate, JsonbValue *fc_string)
{
	JsonbValue *fc_object = &fc_pstate->contVal;

	Assert(fc_object->type == jbvObject);
	Assert(fc_string->type == jbvString);

	if (fc_object->val.object.nPairs >= JSONB_MAX_PAIRS)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
						JSONB_MAX_PAIRS)));

	if (fc_object->val.object.nPairs >= fc_pstate->size)
	{
		fc_pstate->size *= 2;
		fc_object->val.object.pairs = repalloc(fc_object->val.object.pairs,
											sizeof(JsonbPair) * fc_pstate->size);
	}

	fc_object->val.object.pairs[fc_object->val.object.nPairs].key = *fc_string;
	fc_object->val.object.pairs[fc_object->val.object.nPairs].order = fc_object->val.object.nPairs;
}

/*
 * pushJsonbValue() worker:  在生成 Jsonb 时将值对附加到状态
 */
static void fc_appendValue(JsonbParseState *fc_pstate, JsonbValue *fc_scalarVal)
{
	JsonbValue *fc_object = &fc_pstate->contVal;

	Assert(fc_object->type == jbvObject);

	fc_object->val.object.pairs[fc_object->val.object.nPairs++].value = *fc_scalarVal;
}

/*
 * pushJsonbValue() worker:  在生成 Jsonb 时将元素附加到状态
 */
static void fc_appendElement(JsonbParseState *fc_pstate, JsonbValue *fc_scalarVal)
{
	JsonbValue *fc_array = &fc_pstate->contVal;

	Assert(fc_array->type == jbvArray);

	if (fc_array->val.array.nElems >= JSONB_MAX_ELEMS)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
						JSONB_MAX_ELEMS)));

	if (fc_array->val.array.nElems >= fc_pstate->size)
	{
		fc_pstate->size *= 2;
		fc_array->val.array.elems = repalloc(fc_array->val.array.elems,
										  sizeof(JsonbValue) * fc_pstate->size);
	}

	fc_array->val.array.elems[fc_array->val.array.nElems++] = *fc_scalarVal;
}

/*
 * 给定一个 JsonbContainer，扩展为 JsonbIterator 以迭代项目
 * 完全扩展为内存表示以进行操作。
 *
 * 请参见 JsonbIteratorNext() 以获取内存管理的说明。
 */
JsonbIterator *
JsonbIteratorInit(JsonbContainer *fc_container)
{
	return fc_iteratorFromContainer(fc_container, NULL);
}

/*
 * 在迭代时获取下一个 JsonbValue
 *
 * 调用者应最初传递自己的原始迭代器。它们可能会在这里得到
 * 一个在 palloc() 中创建的子迭代器。可以依赖该函数
 * 释放那些子迭代器，避免为高度嵌套对象分配的内存变得不合理，
 * 但前提是调用者没有提前结束迭代
 * （例如，在搜索中找到某些东西时中断）。
 *
 * 在这种情况下，对长时间运行的上下文特别敏感的调用者
 * 可以从最终的迭代器回溯到其最古老的祖先，逐步进行 pfree()。
 * 他们不必释放为迭代器先前分配的任何其他内存
 * 但不作为他们最后返回的迭代器的直接祖先可访问。
 *
 * 返回“Jsonb 顺序处理”标记值。 迭代器“状态”
 * 以较不精细的方式反映该过程的当前阶段，通常在这里用于
 * 跟踪与特定迭代器相关的事物。
 *
 * 此函数的客户端不应处理任何 jbvBinary 值
 * （因为递归调用将处理此问题），前提是 skipNested 为假。
 * 我们的工作是扩展 jbvBinary 表示，而不打扰他们。
 * 但是，客户不应自行处理数组
 * 或对象元素/对缓冲区，因为它们的元素/对指针是
 * 垃圾。此外，返回 WJB_END_ARRAY 或
 * WJB_END_OBJECT 时，*val 不会被设置，假设仅在嵌套访问时对值有用。
 */
JsonbIteratorToken
JsonbIteratorNext(JsonbIterator **fc_it, JsonbValue *fc_val, bool fc_skipNested)
{
	if (*fc_it == NULL)
		return WJB_DONE;

	/*
	 * 当进入嵌套容器时，我们跳回此处开始
	 * 处理子元素。在一次调用中我们不会进一步递归，因为
	 * 处理子元素将始终以 JBI_ARRAY_START 或
	 * JBI_OBJECT_START 状态开始。
	 */
recurse:
	switch ((*fc_it)->state)
	{
		case JBI_ARRAY_START:
			/* 在第一次数组调用时将 v 设置为数组 */
			fc_val->type = jbvArray;
			fc_val->val.array.nElems = (*fc_it)->nElems;

			/*
			 * v->val.array.elems 实际上没有设置，因为我们不是在进行
			 * 完整转换
			 */
			fc_val->val.array.rawScalar = (*fc_it)->isScalar;
			(*fc_it)->curIndex = 0;
			(*fc_it)->curDataOffset = 0;
			(*fc_it)->curValueOffset = 0;	/* 实际上未使用 */
			/* 为下一个调用设置状态 */
			(*fc_it)->state = JBI_ARRAY_ELEM;
			return WJB_BEGIN_ARRAY;

		case JBI_ARRAY_ELEM:
			if ((*fc_it)->curIndex >= (*fc_it)->nElems)
			{
				/*
				 * 数组中的所有元素均已处理。 将此报告给
				 * 调用者，并将其原始父迭代器返回给他们（该迭代器
				 * 在其嵌套级别独立跟踪迭代进度）。
				 */
				*fc_it = fc_freeAndGetParent(*fc_it);
				return WJB_END_ARRAY;
			}

			fc_fillJsonbValue((*fc_it)->container, (*fc_it)->curIndex,
						   (*fc_it)->dataProper, (*fc_it)->curDataOffset,
						   fc_val);

			JBE_ADVANCE_OFFSET((*fc_it)->curDataOffset,
							   (*fc_it)->children[(*fc_it)->curIndex]);
			(*fc_it)->curIndex++;

			if (!IsAJsonbScalar(fc_val) && !fc_skipNested)
			{
				/* 递归进入容器。 */
				*fc_it = fc_iteratorFromContainer(fc_val->val.binary.data, *fc_it);
				goto recurse;
			}
			else
			{
				/*
				 * 数组中的标量项，或一个容器并且调用者不希望
				 * 我们递归进入它。
				 */
				return WJB_ELEM;
			}

		case JBI_OBJECT_START:
			/* 在第一次对象调用时将 v 设置为对象 */
			fc_val->type = jbvObject;
			fc_val->val.object.nPairs = (*fc_it)->nElems;

			/*
			 * v->val.object.pairs 实际上没有设置，因为我们不是在
			 * 进行完整转换
			 */
			(*fc_it)->curIndex = 0;
			(*fc_it)->curDataOffset = 0;
			(*fc_it)->curValueOffset = getJsonbOffset((*fc_it)->container,
												   (*fc_it)->nElems);
			/* 为下一个调用设置状态 */
			(*fc_it)->state = JBI_OBJECT_KEY;
			return WJB_BEGIN_OBJECT;

		case JBI_OBJECT_KEY:
			if ((*fc_it)->curIndex >= (*fc_it)->nElems)
			{
				/*
				 * 对象中的所有对已处理。 将此报告给
				 * 调用者，并将其原始包含迭代器返回给他们
				 * （该迭代器在其嵌套级别独立跟踪迭代进度）。
				 */
				*fc_it = fc_freeAndGetParent(*fc_it);
				return WJB_END_OBJECT;
			}
			else
			{
				/* 返回键/值对的键。 */
				fc_fillJsonbValue((*fc_it)->container, (*fc_it)->curIndex,
							   (*fc_it)->dataProper, (*fc_it)->curDataOffset,
							   fc_val);
				if (fc_val->type != jbvString)
					elog(ERROR, "unexpected jsonb type as object key");

				/* 为下一个调用设置状态 */
				(*fc_it)->state = JBI_OBJECT_VALUE;
				return WJB_KEY;
			}

		case JBI_OBJECT_VALUE:
			/* 为下一个调用设置状态 */
			(*fc_it)->state = JBI_OBJECT_KEY;

			fc_fillJsonbValue((*fc_it)->container, (*fc_it)->curIndex + (*fc_it)->nElems,
						   (*fc_it)->dataProper, (*fc_it)->curValueOffset,
						   fc_val);

			JBE_ADVANCE_OFFSET((*fc_it)->curDataOffset,
							   (*fc_it)->children[(*fc_it)->curIndex]);
			JBE_ADVANCE_OFFSET((*fc_it)->curValueOffset,
							   (*fc_it)->children[(*fc_it)->curIndex + (*fc_it)->nElems]);
			(*fc_it)->curIndex++;

			/*
			 * 值可能是一个容器，在这种情况下，我们使用新的
			 * 子迭代器递归（除非调用者通过传递
			 * skipNested 表示不想）。
			 */
			if (!IsAJsonbScalar(fc_val) && !fc_skipNested)
			{
				*fc_it = fc_iteratorFromContainer(fc_val->val.binary.data, *fc_it);
				goto recurse;
			}
			else
				return WJB_VALUE;
	}

	elog(ERROR, "invalid iterator state");
	return -1;
}

/*
 * 初始化一个迭代器以迭代容器中的所有元素。
 */
static JsonbIterator *
fc_iteratorFromContainer(JsonbContainer *fc_container, JsonbIterator *fc_parent)
{
	JsonbIterator *fc_it;

	fc_it = palloc0(sizeof(JsonbIterator));
	fc_it->container = fc_container;
	fc_it->parent = fc_parent;
	fc_it->nElems = JsonContainerSize(fc_container);

	/* 数组从头部之后开始 */
	fc_it->children = fc_container->children;

	switch (fc_container->header & (JB_FARRAY | JB_FOBJECT))
	{
		case JB_FARRAY:
			fc_it->dataProper =
				(char *) fc_it->children + fc_it->nElems * sizeof(JEntry);
			fc_it->isScalar = JsonContainerIsScalar(fc_container);
			/* 这要么是“原始标量”，要么是数组 */
			Assert(!fc_it->isScalar || fc_it->nElems == 1);

			fc_it->state = JBI_ARRAY_START;
			break;

		case JB_FOBJECT:
			fc_it->dataProper =
				(char *) fc_it->children + fc_it->nElems * sizeof(JEntry) * 2;
			fc_it->state = JBI_OBJECT_START;
			break;

		default:
			elog(ERROR, "unknown type of jsonb container");
	}

	return fc_it;
}

/*
 * JsonbIteratorNext() worker:	返回父级，同时释放当前
 * 迭代器的内存
 */
static JsonbIterator *
fc_freeAndGetParent(JsonbIterator *fc_it)
{
	JsonbIterator *fc_v = fc_it->parent;

	pfree(fc_it);
	return fc_v;
}

/*
 * “包含”运算符函数的工作
 *
 * 从正式上讲，包含是自顶向下的，无序子树同构。
 *
 * 采用属于某种容器类型的迭代器。这些迭代器
 * “属于”那些值，因为它们刚刚在
 * 调用者的上下文中相对于它们进行了初始化（可能是嵌套的方式）。
 *
 * “val”是 lhs Jsonb，mContained 是 rhs Jsonb，当从顶层调用时。
 * 我们确定 mContained 是否包含在 val 中。
 */
bool JsonbDeepContains(JsonbIterator **fc_val, JsonbIterator **fc_mContained)
{
	JsonbValue	fc_vval,
				fc_vcontained;
	JsonbIteratorToken fc_rval,
				fc_rcont;

	/*
	 * 防止由于过于复杂的 Jsonb 导致堆栈溢出。
	 *
	 * 此处独立调用的函数采取了这一预防措施，但这
	 * 可能还不够，因为这也是一个递归函数。
	 */
	check_stack_depth();

	fc_rval = JsonbIteratorNext(fc_val, &fc_vval, false);
	fc_rcont = JsonbIteratorNext(fc_mContained, &fc_vcontained, false);

	if (fc_rval != fc_rcont)
	{
		/*
		 * 不同的返回值可以立即被视为在此嵌套级别
		 * 表示两种不同的容器类型，这就是
		 * 完全放弃的充分理由（但它们都应是某种容器类型）。
		 */
		Assert(fc_rval == WJB_BEGIN_OBJECT || fc_rval == WJB_BEGIN_ARRAY);
		Assert(fc_rcont == WJB_BEGIN_OBJECT || fc_rcont == WJB_BEGIN_ARRAY);
		return false;
	}
	else if (fc_rcont == WJB_BEGIN_OBJECT)
	{
		Assert(fc_vval.type == jbvObject);
		Assert(fc_vcontained.type == jbvObject);

		
/*
		 * 如果 lhs 的对数少于 rhs 的对数，它不可能包含
		 * rhs。 （这个结论是安全的，因为我们在所有 Jsonb 对象中进行了去重；
		 * 因此在数组情况下不可能有相应的优化。）这种情况可能不会经常出现，
		 * 但由于这是一个非常简单的检查，我们不妨做一下。
		 */
		if (fc_vval.val.object.nPairs < fc_vcontained.val.object.nPairs)
			return false;

		/* 处理 rhs "是否包含其中？" 对象 */
		for (;;)
		{
			JsonbValue *fc_lhsVal; /* lhsVal 来自 lhs 对象中的对 */
			JsonbValue	fc_lhsValBuf;

			fc_rcont = JsonbIteratorNext(fc_mContained, &fc_vcontained, false);

			/*
			 * 当我们通过调用者的 rhs "是否包含其中？"
			 * 对象而没有未能找到它的值时，它就是
			 * 包含的。
			 */
			if (fc_rcont == WJB_END_OBJECT)
				return true;

			Assert(fc_rcont == WJB_KEY);
			Assert(fc_vcontained.type == jbvString);

			/* 首先，通过键查找值... */
			fc_lhsVal =
				getKeyJsonValueFromContainer((*fc_val)->container,
											 fc_vcontained.val.string.val,
											 fc_vcontained.val.string.len,
											 &fc_lhsValBuf);
			if (!fc_lhsVal)
				return false;

			/*
			 * ...在这个阶段，很明显至少有一个键
			 * 匹配这个 rhs 对。
			 */
			fc_rcont = JsonbIteratorNext(fc_mContained, &fc_vcontained, true);

			Assert(fc_rcont == WJB_VALUE);

			/*
			 * 使用键比较 rhs 对的值与刚找到的 lhs 对的值
			 */
			if (fc_lhsVal->type != fc_vcontained.type)
			{
				return false;
			}
			else if (IsAJsonbScalar(fc_lhsVal))
			{
				if (!fc_equalsJsonbScalarValue(fc_lhsVal, &fc_vcontained))
					return false;
			}
			else
			{
				/* 嵌套容器值（对象或数组） */
				JsonbIterator *fc_nestval,
						   *fc_nestContained;

				Assert(fc_lhsVal->type == jbvBinary);
				Assert(fc_vcontained.type == jbvBinary);

				fc_nestval = JsonbIteratorInit(fc_lhsVal->val.binary.data);
				fc_nestContained = JsonbIteratorInit(fc_vcontained.val.binary.data);

				/*
				 * 递归匹配 rhs 数据对象对的 "值" 侧。
				 * 这是一个嵌套结构。
				 *
				 * 注意，嵌套仍然必须在正确的
				 * 嵌套子级匹配。然而，每个嵌套级别
				 * 只需要零个或多个匹配对（或元素）
				 * （前提是每个级别的 *rhs* 对/元素 *都*
				 * 匹配），这使得在嵌套结构中搜索
				 * 单个字符串或其他原始类型的子数据相当
				 * 有效（前提是用户构造了 rhs 嵌套
				 * 结构，以便我们 "知道在哪里查找"）。
				 *
				 * 换句话说，rhs "vcontained" Jsonb 中容器节点的映射
				 * 到 lhs 的内部节点是单射的，rhs 上的父子边必须映射
				 * 到 lhs 的父子边以满足包含条件
				 * （当然，映射节点必须相等）。
				 */
				if (!JsonbDeepContains(&fc_nestval, &fc_nestContained))
					return false;
			}
		}
	}
	else if (fc_rcont == WJB_BEGIN_ARRAY)
	{
		JsonbValue *fc_lhsConts = NULL;
		uint32		fc_nLhsElems = fc_vval.val.array.nElems;

		Assert(fc_vval.type == jbvArray);
		Assert(fc_vcontained.type == jbvArray);

		/*
		 * 处理 "原始标量" 伪数组和真正数组之间的区别。
		 *
		 * 一个原始标量可以包含另一个原始标量，一个数组可以
		 * 包含一个原始标量，但一个原始标量不能包含一个数组。我们
		 * 并不对对象情况进行类似的操作，因为对象只能包含对，
		 * 绝不包含原始标量（一个对由一个包含单一对的 rhs 对象参数表示）。
		 */
		if (fc_vval.val.array.rawScalar && !fc_vcontained.val.array.rawScalar)
			return false;

		/* 在 rhs "是否包含在内？" 数组中处理 */
		for (;;)
		{
			fc_rcont = JsonbIteratorNext(fc_mContained, &fc_vcontained, true);

			/*
			 * 当我们通过调用者的 rhs "是否包含在内？"
			 * 数组时没有未能找到其中一个值，就是
			 * 被包含的。
			 */
			if (fc_rcont == WJB_END_ARRAY)
				return true;

			Assert(fc_rcont == WJB_ELEM);

			if (IsAJsonbScalar(&fc_vcontained))
			{
				if (!findJsonbValueFromContainer((*fc_val)->container,
												 JB_FARRAY,
												 &fc_vcontained))
					return false;
			}
			else
			{
				uint32		fc_i;

				/*
				 * 如果这是在 rhs 数组中找到的第一个容器（在此
				 * 深度），初始化临时 lhs 容器数组
				 */
				if (fc_lhsConts == NULL)
				{
					uint32		fc_j = 0;

					/* 为所有可能的值腾出空间 */
					fc_lhsConts = palloc(sizeof(JsonbValue) * fc_nLhsElems);

					for (fc_i = 0; fc_i < fc_nLhsElems; fc_i++)
					{
						/* 将所有 lhs 元素存储在临时数组中 */
						fc_rcont = JsonbIteratorNext(fc_val, &fc_vval, true);
						Assert(fc_rcont == WJB_ELEM);

						if (fc_vval.type == jbvBinary)
							fc_lhsConts[fc_j++] = fc_vval;
					}

					/* 临时数组中没有容器元素，因此现在放弃 */
					if (fc_j == 0)
						return false;

					/* 我们可能只部分填充了数组 */
					fc_nLhsElems = fc_j;
				}

				/* XXX: 嵌套数组包含是 O(N^2) */
				for (fc_i = 0; fc_i < fc_nLhsElems; fc_i++)
				{
					/* 嵌套容器值（对象或数组） */
					JsonbIterator *fc_nestval,
							   *fc_nestContained;
					bool		fc_contains;

					fc_nestval = JsonbIteratorInit(fc_lhsConts[fc_i].val.binary.data);
					fc_nestContained = JsonbIteratorInit(fc_vcontained.val.binary.data);

					fc_contains = JsonbDeepContains(&fc_nestval, &fc_nestContained);

					if (fc_nestval)
						pfree(fc_nestval);
					if (fc_nestContained)
						pfree(fc_nestContained);
					if (fc_contains)
						break;
				}

				/*
				 * 如果无法将 rhs 容器与 *某个* lhs 容器匹配，
				 * 则报告 rhs 容器值不被包含。
				 */
				if (fc_i == fc_nLhsElems)
					return false;
			}
		}
	}
	else
	{
		elog(ERROR, "invalid jsonb container type");
	}

	elog(ERROR, "unexpectedly fell off end of jsonb container");
	return false;
}

/*
 * 对 JsonbValue 标量值进行哈希，将哈希值与调用者提供的现有
 * 哈希混合。
 *
 * 一些调用者可能希望独立地进行 JB_FOBJECT 和 JB_FARRAY
 * 标志的异或运算。
 */
void JsonbHashScalarValue(const JsonbValue *fc_scalarVal, uint32 *fc_hash)
{
	uint32		fc_tmp;

	/* 计算 scalarVal 的哈希值 */
	switch (fc_scalarVal->type)
	{
		case jbvNull:
			fc_tmp = 0x01;
			break;
		case jbvString:
			fc_tmp = DatumGetUInt32(hash_any((const unsigned char *) fc_scalarVal->val.string.val,
										  fc_scalarVal->val.string.len));
			break;
		case jbvNumeric:
			/* 必须将相等的数值哈希为相等的哈希代码 */
			fc_tmp = DatumGetUInt32(DirectFunctionCall1(hash_numeric,
													 NumericGetDatum(fc_scalarVal->val.numeric)));
			break;
		case jbvBool:
			fc_tmp = fc_scalarVal->val.boolean ? 0x02 : 0x04;

			break;
		default:
			elog(ERROR, "invalid jsonb scalar type");
			fc_tmp = 0;			/* 保持编译器安静 */
			break;
	}

	/*
	 * 通过将前一个值左移 1 位，然后将新
	 * 键/值/元素的哈希值异或在一起，组合连续键、值和元素的哈希值。
	 */
	*fc_hash = pg_rotate_left32(*fc_hash, 1);
	*fc_hash ^= fc_tmp;
}

/*
 * 将一个值哈希到一个 64 位值，带有种子。否则，与
 * JsonbHashScalarValue 类似。
 */
void JsonbHashScalarValueExtended(const JsonbValue *fc_scalarVal, uint64 *fc_hash,
							 uint64 fc_seed)
{
	uint64		fc_tmp;

	switch (fc_scalarVal->type)
	{
		case jbvNull:
			fc_tmp = fc_seed + 0x01;
			break;
		case jbvString:
			fc_tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) fc_scalarVal->val.string.val,
												   fc_scalarVal->val.string.len,
												   fc_seed));
			break;
		case jbvNumeric:
			fc_tmp = DatumGetUInt64(DirectFunctionCall2(hash_numeric_extended,
													 NumericGetDatum(fc_scalarVal->val.numeric),
													 UInt64GetDatum(fc_seed)));
			break;
		case jbvBool:
			if (fc_seed)
				fc_tmp = DatumGetUInt64(DirectFunctionCall2(hashcharextended,
														 BoolGetDatum(fc_scalarVal->val.boolean),
														 UInt64GetDatum(fc_seed)));
			else
				fc_tmp = fc_scalarVal->val.boolean ? 0x02 : 0x04;

			break;
		default:
			elog(ERROR, "invalid jsonb scalar type");
			break;
	}

	*fc_hash = ROTATE_HIGH_AND_LOW_32BITS(*fc_hash);
	*fc_hash ^= fc_tmp;
}

/*
 * 两个相同类型的标量 JsonbValues a 和 b 是否相等？
 */
static bool fc_equalsJsonbScalarValue(JsonbValue *fc_aScalar, JsonbValue *fc_bScalar)
{
	if (fc_aScalar->type == fc_bScalar->type)
	{
		switch (fc_aScalar->type)
		{
			case jbvNull:
				return true;
			case jbvString:
				return fc_lengthCompareJsonbStringValue(fc_aScalar, fc_bScalar) == 0;
			case jbvNumeric:
				return DatumGetBool(DirectFunctionCall2(numeric_eq,
														PointerGetDatum(fc_aScalar->val.numeric),
														PointerGetDatum(fc_bScalar->val.numeric)));
			case jbvBool:
				return fc_aScalar->val.boolean == fc_bScalar->val.boolean;

			default:
				elog(ERROR, "invalid jsonb scalar type");
		}
	}
	elog(ERROR, "jsonb scalar type mismatch");
	return false;
}

/*
 * 比较两个标量 JsonbValues，返回 -1、0 或 1。
 *
 * 字符串使用默认的排序规则进行比较。用于 B-tree
 * 操作符，通常期望有一个词法排序顺序。
 */
static int fc_compareJsonbScalarValue(JsonbValue *fc_aScalar, JsonbValue *fc_bScalar)
{
	if (fc_aScalar->type == fc_bScalar->type)
	{
		switch (fc_aScalar->type)
		{
			case jbvNull:
				return 0;
			case jbvString:
				return varstr_cmp(fc_aScalar->val.string.val,
								  fc_aScalar->val.string.len,
								  fc_bScalar->val.string.val,
								  fc_bScalar->val.string.len,
								  DEFAULT_COLLATION_OID);
			case jbvNumeric:
				return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
														 PointerGetDatum(fc_aScalar->val.numeric),
														 PointerGetDatum(fc_bScalar->val.numeric)));
			case jbvBool:
				if (fc_aScalar->val.boolean == fc_bScalar->val.boolean)
					return 0;
				else if (fc_aScalar->val.boolean > fc_bScalar->val.boolean)
					return 1;
				else
					return -1;
			default:
				elog(ERROR, "invalid jsonb scalar type");
		}
	}
	elog(ERROR, "jsonb scalar type mismatch");
	return -1;
}


/*
 * 用于操作 convertJsonb 及其子程序使用的可调整大小的缓冲区的函数。
 */

/*
 * 在缓冲区末尾保留 'len' 字节，必要时扩大它。
 * 返回保留区域的偏移量。期望调用者稍后用 copyToBuffer()
 * 填充保留区域。
 */
static int fc_reserveFromBuffer(StringInfo fc_buffer, int fc_len)
{
	int			fc_offset;

	/* 如果需要，增加更多空间 */
	enlargeStringInfo(fc_buffer, fc_len);

	/* 记住当前偏移量 */
	fc_offset = fc_buffer->len;

	/* 保留空间 */
	fc_buffer->len += fc_len;

	/*
	 * 保持尾随的空值，即使这对我们没有用；保持
	 * StringInfos 的不变性似乎是最好的选择。
	 */
	fc_buffer->data[fc_buffer->len] = '\0';

	return fc_offset;
}

/*
 * 将 'len' 字节复制到缓冲区中的先前保留区域。
 */
static void fc_copyToBuffer(StringInfo fc_buffer, int fc_offset, const char *fc_data, int fc_len)
{
	memcpy(fc_buffer->data + fc_offset, fc_data, fc_len);
}

/*
 * reserveFromBuffer + copyToBuffer 的快捷方式。
 */
static void fc_appendToBuffer(StringInfo fc_buffer, const char *fc_data, int fc_len)
{
	int			fc_offset;

	fc_offset = fc_reserveFromBuffer(fc_buffer, fc_len);
	fc_copyToBuffer(fc_buffer, fc_offset, fc_data, fc_len);
}


/*
 * 添加填充，以便 StringInfo 的长度与整数对齐。
 * 返回附加的填充字节数。
 */
static short
fc_padBufferToInt(StringInfo fc_buffer)
{
	int			fc_padlen,
				fc_p,
				fc_offset;

	fc_padlen = INTALIGN(fc_buffer->len) - fc_buffer->len;

	fc_offset = fc_reserveFromBuffer(fc_buffer, fc_padlen);

	/* padlen 必须很小，因此这可能比 memset 更快 */
	for (fc_p = 0; fc_p < fc_padlen; fc_p++)
		fc_buffer->data[fc_offset + fc_p] = '\0';

	return fc_padlen;
}

/*
 * 给定一个 JsonbValue，转换为 Jsonb。结果是 palloc 申请的。
 */
static Jsonb *
fc_convertToJsonb(JsonbValue *fc_val)
{
	StringInfoData fc_buffer;
	JEntry		fc_jentry;
	Jsonb	   *fc_res;

	/* 不应该已经有二进制表示 */
	Assert(fc_val->type != jbvBinary);

	/* 分配一个输出缓冲区。它将根据需要增大 */
	initStringInfo(&fc_buffer);

	/* 为 varlena 头部留出空间 */
	fc_reserveFromBuffer(&fc_buffer, VARHDRSZ);

	fc_convertJsonbValue(&fc_buffer, &fc_jentry, fc_val, 0);

	/*
	 * 注意：根节点的 JEntry 被丢弃。因此根 JsonbContainer 结构
	 * 必须包含足够的信息来说明它是什么类型的值。
	 */

	fc_res = (Jsonb *) fc_buffer.data;

	SET_VARSIZE(fc_res, fc_buffer.len);

	return fc_res;
}

/*
 * convertJsonb 的子程序：将单个 JsonbValue 序列化为缓冲区。
 *
 * 此节点的 JEntry 头部在 *header 中返回。它填写了该值的长度和适当的类型位。
 * 如果我们希望存储结束偏移量而不是长度，调整的责任在于调用者。
 *
 * 如果该值是数组或对象，则递归处理。'level' 仅用于调试目的。
 */
static void fc_convertJsonbValue(StringInfo fc_buffer, JEntry *fc_header, JsonbValue *fc_val, int fc_level)
{
	check_stack_depth();

	if (!fc_val)
		return;

	/*
	 * 作为 val 传递的 JsonbValue 不应具有 jbvBinary 类型，
	 * 其任何子组件也不应具有该类型。这些值将由 convertJsonbArray 和
	 * convertJsonbObject 产生，结果不会作为参数传回这个函数。
	 */

	if (IsAJsonbScalar(fc_val))
		fc_convertJsonbScalar(fc_buffer, fc_header, fc_val);
	else if (fc_val->type == jbvArray)
		fc_convertJsonbArray(fc_buffer, fc_header, fc_val, fc_level);
	else if (fc_val->type == jbvObject)
		fc_convertJsonbObject(fc_buffer, fc_header, fc_val, fc_level);
	else
		elog(ERROR, "unknown type of jsonb container to convert");
}

static void fc_convertJsonbArray(StringInfo fc_buffer, JEntry *fc_pheader, JsonbValue *fc_val, int fc_level)
{
	int			fc_base_offset;
	int			fc_jentry_offset;
	int			fc_i;
	int			fc_totallen;
	uint32		fc_header;
	int			fc_nElems = fc_val->val.array.nElems;

	/* 记住缓冲区中该数组的起始位置。 */
	fc_base_offset = fc_buffer->len;

	/* 对齐到 4 字节边界（任何填充作为我的数据的一部分） */
	fc_padBufferToInt(fc_buffer);

	/*
	 * 构建头部 Jentry 并将其存储在可变长度有效负载的开始处。
	 */
	fc_header = fc_nElems | JB_FARRAY;
	if (fc_val->val.array.rawScalar)
	{
		Assert(fc_nElems == 1);
		Assert(fc_level == 0);
		fc_header |= JB_FSCALAR;
	}

	fc_appendToBuffer(fc_buffer, (char *) &fc_header, sizeof(uint32));

	/* 为元素的 JEntries 保留空间。 */
	fc_jentry_offset = fc_reserveFromBuffer(fc_buffer, sizeof(JEntry) * fc_nElems);

	fc_totallen = 0;
	for (fc_i = 0; fc_i < fc_nElems; fc_i++)
	{
		JsonbValue *fc_elem = &fc_val->val.array.elems[fc_i];
		int			fc_len;
		JEntry		fc_meta;

		/*
		 * 转换元素，生成 JEntry 并将其可变长度数据附加到缓冲区
		 */
		fc_convertJsonbValue(fc_buffer, &fc_meta, fc_elem, fc_level + 1);

		fc_len = JBE_OFFLENFLD(fc_meta);
		fc_totallen += fc_len;

		/*
		 * 如果总的可变长度数据超过 JEntry 长度字段可以容纳的空间，则退出。
		 * 我们在每个迭代中检查此情况，而不仅仅是在最后一次，以防止可能的整数溢出。
		 */
		if (fc_totallen > JENTRY_OFFLENMASK)
			ereport(ERROR,
					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
					 errmsg("total size of jsonb array elements exceeds the maximum of %u bytes",
							JENTRY_OFFLENMASK)));

		/*
		 * 将每个 JB_OFFSET_STRIDE 的长度转换为偏移量。
		 */
		if ((fc_i % JB_OFFSET_STRIDE) == 0)
			fc_meta = (fc_meta & JENTRY_TYPEMASK) | fc_totallen | JENTRY_HAS_OFF;

		fc_copyToBuffer(fc_buffer, fc_jentry_offset, (char *) &fc_meta, sizeof(JEntry));
		fc_jentry_offset += sizeof(JEntry);
	}

	/* 总数据大小是我们已附加到缓冲区的所有内容 */
	fc_totallen = fc_buffer->len - fc_base_offset;

	/* 再次检查长度，因为我们没有包括上述的元数据 */
	if (fc_totallen > JENTRY_OFFLENMASK)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("total size of jsonb array elements exceeds the maximum of %u bytes",
						JENTRY_OFFLENMASK)));

	/* 初始化该节点在容器的 JEntry 数组中的头部 */
	*fc_pheader = JENTRY_ISCONTAINER | fc_totallen;
}

static void fc_convertJsonbObject(StringInfo fc_buffer, JEntry *fc_pheader, JsonbValue *fc_val, int fc_level)
{
	int			fc_base_offset;
	int			fc_jentry_offset;
	int			fc_i;
	int			fc_totallen;
	uint32		fc_header;
	int			fc_nPairs = fc_val->val.object.nPairs;

	/* 记住缓冲区中该对象的起始位置。 */
	fc_base_offset = fc_buffer->len;

	/* 对齐到 4 字节边界（任何填充作为我的数据的一部分） */
	fc_padBufferToInt(fc_buffer);

	/*
	 * 构建头部 Jentry 并将其存储在可变长度有效负载的开始处。
	 */
	fc_header = fc_nPairs | JB_FOBJECT;
	fc_appendToBuffer(fc_buffer, (char *) &fc_header, sizeof(uint32));

	/* 为键和值的 JEntries 保留空间。 */
	fc_jentry_offset = fc_reserveFromBuffer(fc_buffer, sizeof(JEntry) * fc_nPairs * 2);

	/*
	 * 先遍历键，然后遍历值，因为这是我们想要的磁盘
	 * 表示顺序。
	 */
	fc_totallen = 0;
	for (fc_i = 0; fc_i < fc_nPairs; fc_i++)
	{
		JsonbPair  *fc_pair = &fc_val->val.object.pairs[fc_i];
		int			fc_len;
		JEntry		fc_meta;

		/*
		 * 转换键，生成 JEntry 并将其可变长度数据附加到缓冲区
		 */
		fc_convertJsonbScalar(fc_buffer, &fc_meta, &fc_pair->key);

		fc_len = JBE_OFFLENFLD(fc_meta);
		fc_totallen += fc_len;

		/*
		 * 如果总的可变长度数据超过 JEntry 长度字段可以容纳的空间，则退出。
		 * 我们在每个迭代中检查此情况，而不仅仅是在最后一次，以防止可能的整数溢出。
		 */
		if (fc_totallen > JENTRY_OFFLENMASK)
			ereport(ERROR,
					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
					 errmsg("total size of jsonb object elements exceeds the maximum of %u bytes",
							JENTRY_OFFLENMASK)));

		/*
		 * 将每个 JB_OFFSET_STRIDE 的长度转换为偏移量。
		 */
		if ((fc_i % JB_OFFSET_STRIDE) == 0)
			fc_meta = (fc_meta & JENTRY_TYPEMASK) | fc_totallen | JENTRY_HAS_OFF;

		fc_copyToBuffer(fc_buffer, fc_jentry_offset, (char *) &fc_meta, sizeof(JEntry));
		fc_jentry_offset += sizeof(JEntry);
	}
	for (fc_i = 0; fc_i < fc_nPairs; fc_i++)
	{
		JsonbPair  *fc_pair = &fc_val->val.object.pairs[fc_i];
		int			fc_len;
		JEntry		fc_meta;

		/*
		 * 转换值，生成 JEntry 并将其可变长度数据附加到缓冲区
		 */
		fc_convertJsonbValue(fc_buffer, &fc_meta, &fc_pair->value, fc_level + 1);

		fc_len = JBE_OFFLENFLD(fc_meta);
		fc_totallen += fc_len;

		/*
		 * 如果总的可变长度数据超过 JEntry 长度字段可以容纳的空间，则退出。
		 * 我们在每个迭代中检查此情况，而不仅仅是在最后一次，以防止可能的整数溢出。
		 */
		if (fc_totallen > JENTRY_OFFLENMASK)
			ereport(ERROR,
					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
					 errmsg("total size of jsonb object elements exceeds the maximum of %u bytes",
							JENTRY_OFFLENMASK)));

		/*
		 * 将每个 JB_OFFSET_STRIDE 的长度转换为偏移量。
		 */
		if (((fc_i + fc_nPairs) % JB_OFFSET_STRIDE) == 0)
			fc_meta = (fc_meta & JENTRY_TYPEMASK) | fc_totallen | JENTRY_HAS_OFF;

		fc_copyToBuffer(fc_buffer, fc_jentry_offset, (char *) &fc_meta, sizeof(JEntry));
		fc_jentry_offset += sizeof(JEntry);
	}

	/* 总数据大小是我们已附加到缓冲区的所有内容 */
	fc_totallen = fc_buffer->len - fc_base_offset;

	/* 再次检查长度，因为我们没有包括上述的元数据 */
	if (fc_totallen > JENTRY_OFFLENMASK)
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("total size of jsonb object elements exceeds the maximum of %u bytes",
						JENTRY_OFFLENMASK)));

	/* 初始化该节点在容器的 JEntry 数组中的头部 */
	*fc_pheader = JENTRY_ISCONTAINER | fc_totallen;
}

static void fc_convertJsonbScalar(StringInfo fc_buffer, JEntry *fc_jentry, JsonbValue *fc_scalarVal)
{
	int			fc_numlen;
	short		fc_padlen;

	switch (fc_scalarVal->type)
	{
		case jbvNull:
			*fc_jentry = JENTRY_ISNULL;
			break;

		case jbvString:
			fc_appendToBuffer(fc_buffer, fc_scalarVal->val.string.val, fc_scalarVal->val.string.len);

			*fc_jentry = fc_scalarVal->val.string.len;
			break;

		case jbvNumeric:
			fc_numlen = VARSIZE_ANY(fc_scalarVal->val.numeric);
			fc_padlen = fc_padBufferToInt(fc_buffer);

			fc_appendToBuffer(fc_buffer, (char *) fc_scalarVal->val.numeric, fc_numlen);

			*fc_jentry = JENTRY_ISNUMERIC | (fc_padlen + fc_numlen);
			break;

		case jbvBool:
			*fc_jentry = (fc_scalarVal->val.boolean) ?
				JENTRY_ISBOOL_TRUE : JENTRY_ISBOOL_FALSE;
			break;

		case jbvDatetime:
			{
				char		fc_buf[MAXDATELEN + 1];
				size_t		fc_len;

				JsonEncodeDateTime(fc_buf,
								   fc_scalarVal->val.datetime.value,
								   fc_scalarVal->val.datetime.typid,
								   &fc_scalarVal->val.datetime.tz);
				fc_len = strlen(fc_buf);
				fc_appendToBuffer(fc_buffer, fc_buf, fc_len);

				*fc_jentry = fc_len;
			}
			break;

		default:
			elog(ERROR, "invalid jsonb scalar type");
	}
}

/*
 * 比较两个 jbvString JsonbValue 值，a 和 b。
 *
 * 这是一个特殊的 qsort() 比较器，用于在某些内部上下文中对字符串进行排序
 * 在这些上下文中，拥有明确定义的排序顺序就足够了。
 * 特别是，按对键对对象进行排序以便于便宜的二进制搜索，
 * 我们不关心词法排序顺序。
 *
 * a 和 b 首先根据其长度进行排序。如果需要破平局的方式，
 * 则只有在此时我们才考虑字符串的二进制相等性。
 */
static int fc_lengthCompareJsonbStringValue(const void *fc_a, const void *fc_b)
{
	const JsonbValue *fc_va = (const JsonbValue *) fc_a;
	const JsonbValue *fc_vb = (const JsonbValue *) fc_b;

	Assert(fc_va->type == jbvString);
	Assert(fc_vb->type == jbvString);

	return fc_lengthCompareJsonbString(fc_va->val.string.val, fc_va->val.string.len,
									fc_vb->val.string.val, fc_vb->val.string.len);
}

/*
 * lengthCompareJsonbStringValue 的子程序
 *
 * 这在单独实现 JsonbContainers 上的二进制搜索时也很有用。
 */
static int fc_lengthCompareJsonbString(const char *fc_val1, int fc_len1, const char *fc_val2, int fc_len2)
{
	if (fc_len1 == fc_len2)
		return memcmp(fc_val1, fc_val2, fc_len1);
	else
		return fc_len1 > fc_len2 ? 1 : -1;
}

/*
 * qsort_arg() 比较器，用于比较 JsonbPair 值。
 *
 * 第三个参数 'binequal' 可以指向一个 bool。如果设置了，
 * 则当且仅当 a 和 b 具有完全的二进制相等时，*binequal 被设置为 true，
 * 因为某些调用者对两个值是否相等或仅相当感兴趣。
 *
 * N.B: 此处字符串比较是 "按照长度" 的
 *
 * 具有相等键的对的顺序是尊重顺序字段的。
 */
static int fc_lengthCompareJsonbPair(const void *fc_a, const void *fc_b, void *fc_binequal)
{
	const JsonbPair *fc_pa = (const JsonbPair *) fc_a;
	const JsonbPair *fc_pb = (const JsonbPair *) fc_b;
	int			fc_res;

	fc_res = fc_lengthCompareJsonbStringValue(&fc_pa->key, &fc_pb->key);
	if (fc_res == 0 && fc_binequal)
		*((bool *) fc_binequal) = true;

	/*
	 * 确保保持相等对的顺序。独特算法将优先选择第一个元素作为值。
	 */
	if (fc_res == 0)
		fc_res = (fc_pa->order > fc_pb->order) ? -1 : 1;

	return fc_res;
}

/*
 * 对 JsonbValue 对象中的对进行排序和唯一化
 */
static void fc_uniqueifyJsonbObject(JsonbValue *fc_object)
{
	bool		fc_hasNonUniq = false;

	Assert(fc_object->type == jbvObject);

	if (fc_object->val.object.nPairs > 1)
		qsort_arg(fc_object->val.object.pairs, fc_object->val.object.nPairs, sizeof(JsonbPair),
				  fc_lengthCompareJsonbPair, &fc_hasNonUniq);

	if (fc_hasNonUniq)
	{
		JsonbPair  *fc_ptr = fc_object->val.object.pairs + 1,
				   *fc_res = fc_object->val.object.pairs;

		while (fc_ptr - fc_object->val.object.pairs < fc_object->val.object.nPairs)
		{
			/* 避免复制重复项 */
			if (fc_lengthCompareJsonbStringValue(fc_ptr, fc_res) != 0)
			{
				fc_res++;
				if (fc_ptr != fc_res)
					memcpy(fc_res, fc_ptr, sizeof(JsonbPair));
			}
			fc_ptr++;
		}

		fc_object->val.object.nPairs = fc_res + 1 - fc_object->val.object.pairs;
	}
}
